
#ifndef __POSIX_FSM_H__
#define __POSIX_FSM_H__

#include <stdint.h>
#include "pthread_lock.h"

/* 使用方法：
 * 1.依据用户需求, 建立 fsm_event_handle 表, 枚举事件/状态;      
 * 2.创建 fsm_t 对象, 并将 fsm_event_handle 与之绑定;
 * 3.根据用户程序需求设定不同 event 以调用 fsm_event_exec() 执行对应动作;
 * 约定 <当前状态 + 一个事件> 只能有一个 动作回调 ,一般会设置一个事件为特权级事件(常用于挂起)
 */
 /*
 *      |------|  event1 |------|
 *      |state1| ------> |state2|
 *      |------| <------ |------|
 *        | /|\   event2   | /|\
 *  event3|  | event4      |  |
 *       \|/ |             |  |
 *      |------|   event5  |  | event6
 *      |state3|<-----------  |
 *      |------|--------------
 */
//=================================================宏定义========================================================//
#ifdef __cplusplus
extern "C" {
#endif //__cplusplus

//================================================类型声明=======================================================//
typedef enum {
	FSM_RT_OK = 0,	
	
	FSM_VIE_LOCK,	//竞争锁
	FSM_GO_TRAP,	//陷入陷阱
	FSM_UNKNOWN		//未知错误
}fsm_result;

/**
 * @brief 	触发事件执行动作回调
 * @param 	void *  : 事件参数
 * @retval	int 	: 转移状态
 * @note	/
 */
typedef int (*fsm_event_cb)(void *);

/* 事件处理/状态转移 */
typedef struct {
    int cur_state;				//当前状态
    int trigger_event;			//触发事件
    fsm_event_cb do_action;		//动作回调(如未定义-即NULL, 则表示当前事件无动作, 直接转移状态)
	int next_state;				//转移状态
}fsm_handle_t;

/* 状态机句柄 */
typedef struct {
    int state;				//维护状态变量
    fsm_handle_t *table;	//状态迁移表
    unsigned int table_num;	//状态迁移表大小
	pthread_mutex_t mutex;	//互斥锁保持访问状态变量的原子性
}fsm_t;

//================================================函数声明=======================================================//
/**
 * @brief 	获取当前状态
 * @param 	fsm   : 状态机句柄
 *			state : 当前状态
 * @retval	详见 fsm_result 枚举
 * @note	\
 */
fsm_result fsm_state_get(fsm_t *fsm, int *state);

/**
 * @brief 	切换当前状态
 * @param 	fsm   : 状态机句柄
 *			state : 期望状态
 * @retval	详见 fsm_result 枚举
 * @note	\
 */
fsm_result fsm_state_set(fsm_t *fsm, int state);

/**
 * @brief 	通过该方法获取在当前状态下, 指定事件到来时的对应动作处理回调
 * @param 	fsm   		 : 状态机句柄
 *			event 		 : 触发事件
 *			fsm_event_cb : 动作执行回调
 * @retval	详见 fsm_result 枚举
 * @note	/
 */
fsm_result fsm_event_handler_get(fsm_t *fsm, int event, fsm_event_cb *action);

/**
 * @brief 	当指定事件触发时, 状态机会自动寻找并调用对应的动作处理回调, 从而完成状态转移
 * @param 	fsm   : 状态机句柄
 *			event : 触发事件
 *			data  : 事件参数
 * @retval	详见 fsm_result 枚举
 * @note	/
 */
fsm_result fsm_event_exec(fsm_t *fsm, int event, void *data);

#ifdef __cplusplus
}
#endif //__cplusplus

#endif //__POSIX_FSM_H__
